home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / utility / btoa52.zip / BTOA.C < prev    next >
C/C++ Source or Header  |  1994-04-08  |  8KB  |  356 lines

  1. /* btoa.c */
  2.  
  3. /* Written by Paul Rutter, Joe Orost & Stefan Parmark. */
  4.  
  5. #include <stdio.h>
  6. #ifdef AMIGA
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #endif AMIGA
  10.  
  11. #include "btoa.h"
  12. #if USE_MACROS
  13. #include "chksum.h"
  14. #endif USE_MACROS
  15.  
  16. #define VERSION  "5.2"
  17.  
  18. LONG Ceor, Csum, Crot;  /* Checksums to verify archive validity. */
  19. BYTE new_version, openoutput, buffer[BUFSIZE];
  20. FILE *outfile;
  21.  
  22.  
  23. void main(argc, argv)
  24. int argc;
  25. BYTE **argv;
  26. {
  27.   register BYTE openinput, error, ch, a_to_b, diagnosis, repair;
  28.   register BYTE *infilename, *text;
  29.   register FILE *infile;
  30.   extern BYTE new_version, openoutput;
  31.   extern FILE *outfile;
  32. #ifdef AMIGA
  33.   extern int _bufsiz;
  34.  
  35.   /* Change file buffer size. */
  36.   _bufsiz = 10240;
  37. #endif AMIGA
  38.  
  39.   error = openinput = openoutput = a_to_b = diagnosis = repair = FALSE;
  40.   new_version = TRUE;
  41.   infilename = NULL;
  42.  
  43.   /* Scan for '-' options. The rest must be file names. */
  44.   while (!error && argc > 1 && *argv[1] == '-')
  45.   {
  46.     text = &argv[1][1];
  47.     while (!error && (ch = *text++) != 0)
  48.     {
  49.       switch(ch)
  50.       {
  51.         case 'a' : /* Activate atob. */
  52.                    a_to_b = TRUE;
  53.                    break;
  54.         case 'd' : /* Extract missing part from undamaged archive. */
  55.                    diagnosis = TRUE;
  56.                    break;
  57.         case 'h' : /* Print help and abort execution. */
  58.                    error = TRUE;
  59.                    break;
  60.         case 'o' : /* Use old btoa format. */
  61.                    new_version = FALSE;
  62.                    break;
  63.         case 'r' : /* Repair damaged archive. */
  64.                    repair = TRUE;
  65.                    break;
  66.         default  : error = TRUE;
  67.       }
  68.     }
  69.     argv++;
  70.     argc--;
  71.   }
  72.  
  73.   if (argc > 3)
  74.     error = TRUE;
  75.  
  76.   if (error)
  77.     printhelp();
  78.   else
  79.   {
  80.     /* If file name was given, try to open file. Otherwise use stdin. */
  81.     if (argc > 1)
  82.     {
  83.       infilename = argv[1];
  84.       if ((infile = fopen_read(infilename)) == NULL)
  85.         error = TRUE;
  86.       else
  87.         openinput = TRUE;
  88.     }
  89.     else
  90.       infile = stdin;
  91.   }
  92.  
  93.   if (!error)
  94.   {
  95.     /* If file name was given, try to open file. Otherwise use stdout. */
  96.     if (argc > 2 && !diagnosis && !repair)
  97.     {
  98.       if ((outfile = fopen_write(argv[2])) == NULL)
  99.         error = TRUE;
  100.       else
  101.         openoutput = TRUE;
  102.     }
  103.     else
  104.       outfile = stdout;
  105.   }
  106.  
  107.   if (!error)
  108.   {
  109.     if (diagnosis)
  110.       error = producerepair(infile);
  111.     else if (repair)
  112.       error = performrepair(infile);
  113.     else if (a_to_b)
  114.       error = atob(infile);
  115.     else
  116.       error = btoa(infile, infilename);
  117.   }
  118.  
  119.   /* Close all opened files. */
  120.   if (openinput)
  121.     fclose(infile);
  122.   if (openoutput)
  123.     fclose(outfile);
  124.  
  125.   if (error)
  126.     exit(1);
  127. }
  128.  
  129.  
  130. BYTE btoa(infile, infilename)
  131. register FILE *infile;
  132. register BYTE *infilename;
  133. {
  134.   register LONG codeword, filesize;
  135.   register int ch1, ch2, ch3, ch4, readbytes;
  136.   extern FILE *outfile;
  137.   extern BYTE new_version, buffer[BUFSIZE];
  138.   extern LONG Ceor, Csum, Crot;
  139.  
  140.   Ceor = Csum = Crot = 0;
  141.  
  142.   /* Write archive header. */
  143.   if (new_version)
  144.   {
  145.     fprintf(outfile, "xbtoa5 %d %s Begin\n", MAXPERLINE,
  146.         (infilename == NULL) ? "-" : truncname(infilename));
  147.   }
  148.   else
  149.     fprintf(outfile, "xbtoa Begin\n");
  150.  
  151.   /* Encode entire input file. */
  152.   filesize = 0;
  153.   do
  154.   {
  155.     readbytes = fread(buffer, 1, 4, infile);
  156.  
  157.     if (readbytes < 4)
  158.     {
  159.       ch1 = (readbytes > 0) ? ((int)buffer[0] & 0xFF) : 0;
  160.       ch2 = (readbytes > 1) ? ((int)buffer[1] & 0xFF) : 0;
  161.       ch3 = (readbytes > 2) ? ((int)buffer[2] & 0xFF) : 0;
  162.       ch4 = 0;
  163.     }
  164.     else
  165.     {
  166.       ch1 = (int)buffer[0] & 0xFF;
  167.       ch2 = (int)buffer[1] & 0xFF;
  168.       ch3 = (int)buffer[2] & 0xFF;
  169.       ch4 = (int)buffer[3] & 0xFF;
  170.     }
  171.  
  172.     if (readbytes > 0)
  173.     {
  174.       if (!new_version)
  175.       {
  176.         calcchecksum(ch1);
  177.         calcchecksum(ch2);
  178.         calcchecksum(ch3);
  179.         calcchecksum(ch4);
  180.       }
  181.  
  182.       codeword = (ch1 << 8) | ch2;
  183.       codeword = (((codeword << 8) | ch3) << 8) | ch4;
  184.       wordout(codeword);
  185.  
  186.       filesize += readbytes;
  187.     }
  188.   }
  189.   while (readbytes == 4);
  190.  
  191.   asciiout(EOF);  /* Flush buffer. */
  192.  
  193.   /* Filesize is written twice as crude cross check. */
  194.   fprintf(outfile, "xbtoa End N %ld %lx E %lx S %lx R %lx\n",
  195.         filesize, filesize, Ceor, Csum, Crot);
  196.  
  197.   return(FALSE);  /* No errors discovered. */
  198. }
  199.  
  200.  
  201. /* Print help on how to use btoa. */
  202. void printhelp()
  203. {
  204.   fprintf(stderr, "              Btoa version %s\n", VERSION);
  205.   fprintf(stderr, "Written by Paul Rutter, Joe Orost & Stefan Parmark.\n");
  206.  
  207.   fprintf(stderr, "\nUsage: btoa [-{adhor}] [input file] [output file]\n");
  208.  
  209.   fprintf(stderr, "\nOptions:\n");
  210.   fprintf(stderr, "-h  Shows this help list.\n");
  211.   fprintf(stderr, "-a  Use atob rather than btoa.\n");
  212.   fprintf(stderr, "-o  Use old version of btoa.\n");
  213.   fprintf(stderr, "-d  Extract repair file from diagnosis file.\n");
  214.   fprintf(stderr, "-r  Repair archive from repair file.\n");
  215.  
  216.   fprintf(stderr, "\nExamples:\n");
  217.   fprintf(stderr, "  btoa -h\n");
  218.   fprintf(stderr, "  btoa [input binary file] [output archive file]\n");
  219.   fprintf(stderr, "  btoa -o [input binary file] [output archive file]\n");
  220.   fprintf(stderr, "  btoa -a [input archive file] [output binary file]\n");
  221.   fprintf(stderr, "  btoa -d [undamaged archive file]\n");
  222.   fprintf(stderr, "  btoa -r [damaged archive file]\n");
  223. }
  224.  
  225.  
  226. #if !USE_MACROS
  227. /* Update file checksums. */
  228. void calcchecksum(ch)
  229. register int ch;
  230. {
  231.   extern LONG Ceor, Csum, Crot;
  232.  
  233.   Ceor ^= ch;
  234.   Csum += ch + 1;
  235.  
  236.   if (Crot & 0x80000000L)
  237.     ch ++;
  238.   Crot <<= 1;
  239.   Crot += ch;
  240. }
  241. #endif !USE_MACROS
  242.  
  243.  
  244. /* Encode 4 binary bytes to 5 ascii bytes. */
  245. void wordout(codeword)
  246. register LONG codeword;
  247. {
  248.   register int tmp, quote;
  249.   extern BYTE new_version;
  250.  
  251.   if (codeword == 0)
  252.     /* Encode 4 zeros as a 'z'. */
  253.     asciiout('z');
  254.   else if (new_version && codeword == 0x20202020)
  255.     /* Encode 4 spaces as a 'y'. */
  256.     asciiout('y');
  257.   else
  258.   {
  259.     tmp = 0;
  260.  
  261.     /* Extra calculations because some machines don't support */
  262.     /* unsigned longwords.                                    */
  263.     if (codeword < 0)
  264.     {
  265.       tmp = 32;
  266.       codeword -= (LONG)(85L * 85 * 85 * 85 * 32);
  267.     }
  268.     if (codeword < 0)
  269.     {
  270.       tmp = 64;
  271.       codeword -= (LONG)(85L * 85 * 85 * 85 * 32);
  272.     }
  273.  
  274.     /* Write 5 ascii bytes representing 4 binary bytes. */
  275.  
  276.     quote = codeword / (LONG)(85L * 85 * 85 * 85);
  277.     codeword -= quote * (LONG)(85L * 85 * 85 * 85);
  278.     asciiout(ENCODE(quote + tmp));
  279.  
  280.     quote = codeword / (LONG)(85L * 85 * 85);
  281.     codeword -= quote * (LONG)(85L * 85 * 85);
  282.     asciiout(ENCODE(quote));
  283.  
  284.     quote = codeword / (LONG)(85L * 85);
  285.     codeword -= quote * (LONG)(85L * 85);
  286.     asciiout(ENCODE(quote));
  287.  
  288.     quote = (int)codeword / 85;
  289.     codeword -= quote * 85;
  290.     asciiout(ENCODE(quote));
  291.  
  292.     asciiout(ENCODE((int)codeword));
  293.   }
  294. }
  295.  
  296.  
  297. /* Write ch to outfile. Write '\n' for every line. */
  298. void asciiout(ch)
  299. register int ch;
  300. {
  301.   static WORD linepos = 0;
  302.   extern FILE *outfile;
  303.   extern LONG Csum;
  304.   extern BYTE new_version;
  305.  
  306.   if (ch == EOF)  /* Signal to flush buffer. */
  307.   {
  308.     /* Linepos == 0 means '\n' just written in asciiout(). This */
  309.     /* avoids bug in BITNET, which changes blank line to spaces. */
  310.     if (linepos != 0)
  311.     {
  312.       if (new_version)
  313.         fputc(ENCODE(Csum % 85), outfile); /* Checksum for every line. */
  314.       fputc('\n', outfile);
  315.     }
  316.   }
  317.   else
  318.   {
  319.     fputc(ch, outfile);
  320.     linepos ++;
  321.  
  322.     if (new_version)
  323.     {
  324.       calcchecksum(ch);
  325.       if (linepos >= (MAXPERLINE-1))
  326.       {
  327.         fputc(ENCODE(Csum % 85), outfile); /* Checksum for every line. */
  328.         fputc('\n', outfile);
  329.         linepos = 0;
  330.       }
  331.     }
  332.     else  /* Old version */
  333.       if (linepos >= MAXPERLINE)
  334.       {
  335.         fputc('\n', outfile);
  336.         linepos = 0;
  337.       }
  338.  
  339.   }
  340. }
  341.  
  342.  
  343. /* Remove paths from a file name. */
  344. BYTE *truncname(name)
  345. register BYTE *name;
  346. {
  347.   register BYTE ch, *newname;
  348.  
  349.   newname = name;
  350.   while ((ch = *name++) != 0)
  351.     if (ch == '/' || ch == ':')
  352.       newname = name;
  353.  
  354.   return(newname);
  355. }
  356.